package co.edu.unal.bioingenium.kbmed.retrieval.knowledge.similarity;

import co.edu.unal.bioingenium.kbmed.features.CompactFeatureVector;
import gnu.trove.map.TIntIntMap;

/**
 * Implementation based on description in paper:
 * MedSearch: A Retrieval System for Medical Information Based on Semantic Similarity
 * @author Ing. Alejandro Riveros Cruz
 */
public class CosineExtendend {

    /**
     *
     * @param x1 
     * @param x2 
     * @param corpusIndexMatrixIndexMap 
     * @param similarityMatrix 
     * @return 
     */
    public float getValue(CompactFeatureVector x1, CompactFeatureVector x2, TIntIntMap corpusIndexMatrixIndexMap, float[][] similarityMatrix) {
        float cos, num, dem1, dem2;
        num = 0;
        dem1 = 0;
        dem2 = 0;
        int[] index1 = x1.getIndexKeys();
        int[] index2 = x2.getIndexKeys();
        for (int index1Key : index1) {
            for (int index2Key : index2) {
                num = num + x1.getValue(index1Key) * x2.getValue(index2Key) * similarityMatrix[corpusIndexMatrixIndexMap.get(index1Key)][corpusIndexMatrixIndexMap.get(index2Key)];
            }
        }
        for (int index1Key : index1) {
            dem1 = dem1 + (float) Math.pow(x1.getValue(index1Key), 2);
        }
        for (int index2Key : index2) {
            dem2 = dem2 + (float) Math.pow(x2.getValue(index2Key), 2);
        }
        dem1 = (float) Math.sqrt(dem1);
        dem2 = (float) Math.sqrt(dem2);
        cos = num / (dem1 * dem2);
        if (Float.valueOf(cos).isNaN()) {
            return 0;
        }
        return cos;
    }
}
